package com.hrg.rds.biz.waybill.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hrg.rds.biz.waybill.domain.template.TemplateParam;
import com.hrg.rds.biz.waybill.domain.template.WaybillTemplate;
import com.hrg.rds.biz.waybill.domain.template.WaybillTemplateDto;
import com.hrg.rds.biz.waybill.domain.template.WaybillTemplateVo;
import com.hrg.rds.biz.waybill.domain.template.cmd.Cmd;
import com.hrg.rds.biz.waybill.domain.template.cmd.CmdDto;
import com.hrg.rds.biz.waybill.domain.template.cmd.CmdParam;
import com.hrg.rds.biz.waybill.domain.template.cmd.CmdVo;
import com.hrg.rds.biz.waybill.mapper.CmdMapper;
import com.hrg.rds.biz.waybill.mapper.WaybillTemplateMapper;
import com.hrg.rds.biz.waybill.service.WaybillTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class WaybillTemplateServiceImpl implements WaybillTemplateService {
    @Autowired
    private WaybillTemplateMapper waybillTemplateMapper;
    @Autowired
    private CmdMapper cmdMapper;

    @Override
    public List<WaybillTemplateVo> selectList(WaybillTemplateDto waybillTemplateDto) {
        List<WaybillTemplate> waybillTemplates = waybillTemplateMapper.selectList(waybillTemplateDto);
        if (CollUtil.isEmpty(waybillTemplates)) {
            return Collections.emptyList();
        }
        List<WaybillTemplateVo> waybillTemplateVoList = new ArrayList<>();

        List<String> waybillTemplateIds = waybillTemplates.stream().map(WaybillTemplate::getId).toList();
        List<Cmd> cmds = cmdMapper.selectList(CmdDto.builder().waybillTemplateIds(waybillTemplateIds).build());
        Map<String, List<Cmd>> map = cmds.stream().collect(Collectors.groupingBy(Cmd::getWaybillTemplateId));

        waybillTemplates.forEach(waybillTemplate -> {
            WaybillTemplateVo waybillTemplateVo = new WaybillTemplateVo();
            waybillTemplateVo.setId(waybillTemplate.getId());
            waybillTemplateVo.setName(waybillTemplate.getName());
            waybillTemplateVo.setVersion(waybillTemplate.getVersion());
            waybillTemplateVo.setIfScheduled(waybillTemplate.isIfScheduled());
            waybillTemplateVo.setDelaySeconds(waybillTemplate.getDelaySeconds());
            waybillTemplateVo.setPeriodSeconds(waybillTemplate.getPeriodSeconds());
            waybillTemplateVo.setInputParams(JSONUtil.toList(waybillTemplate.getInputParams(), TemplateParam.class));
            waybillTemplateVo.setOutputParams(JSONUtil.toList(waybillTemplate.getOutputParams(), TemplateParam.class));
            waybillTemplateVo.setGiveWayPriority(waybillTemplate.getGiveWayPriority());
            CmdVo rootCmdVo = buildCmdVoTree(map.get(waybillTemplate.getId()));
            waybillTemplateVo.setRootCmdVo(rootCmdVo);
            waybillTemplateVo.setIfEnabled(waybillTemplate.isIfEnabled());
            waybillTemplateVoList.add(waybillTemplateVo);
        });
        return waybillTemplateVoList;
    }

    public CmdVo buildCmdVoTree(List<Cmd> cmds) {
        List<CmdVo> cmdVos = new ArrayList<>();
        cmds.forEach(cmd -> {
            CmdVo cmdVo = new CmdVo();
            cmdVo.setId(cmd.getId());
            cmdVo.setName(cmd.getName());
            cmdVo.setParentId(cmd.getParentId());
            cmdVo.setChildren(new ArrayList<>());
            cmdVo.setWaybillTemplateId(cmd.getWaybillTemplateId());
            cmdVo.setCmdType(cmd.getCmdType());
            cmdVo.setOrder(cmd.getOrder());
            cmdVo.setInputParams(JSONUtil.toList(cmd.getInputParams(), CmdParam.class));
            cmdVo.setOutputParams(JSONUtil.toList(cmd.getOutputParams(), CmdParam.class));
            cmdVos.add(cmdVo);
        });
        CmdVo rootCmdVo = null;
        Map<String, CmdVo> map = cmdVos.stream().collect(Collectors.toMap(CmdVo::getId, Function.identity()));
        for (CmdVo cmdVo : cmdVos) {
            if (StrUtil.isBlank(cmdVo.getParentId())) {
                rootCmdVo = cmdVo;
            } else {
                CmdVo parentCmdVo = map.get(cmdVo.getParentId());
                parentCmdVo.getChildren().add(cmdVo);
            }
        }
        map.values().forEach(cmdVo -> cmdVo.getChildren().sort(Comparator.comparingInt(CmdVo::getOrder)));
        return rootCmdVo;
    }

}
